\chapter{Evaluatie}
\label{Evaluatie}

Het prototype werd op zowel performantie als op beveiliging ge\"valueerd. De evaluatie van de performantie is redelijk beperkt gebleven omdat goede performantie niet in de focus van deze thesis was. 
Enkel de laadtijd en functie uitvoeringstijd zijn ge\"evalueerd geweest.  De evaluatie van de beveiliging was veel grondiger.
We hebben hiervoor het prototype getest op bekende aanvallen op andere technieken uit de literatuur en op bekende cross site scripting aanvallen. De prototype was al veilig tegen een heel deel aanvallen maar toch moesten er nog aanpassingen doorgevoerd worden om alle geteste aanvallen tegen te gaan. Dit heeft ook een paar beperkingen met zich meegebracht die op het einde van dit hoofdstuk beschreven worden.

\section{Performantie overhead}

Om een beter zicht te krijgen op de performantie overhead van het prototype ten opzichte van pagina laadtijd en code uitvoering zijn er performantie tests uitgevoerd.
De tests zijn uitgevoerd op Mozilla Firefox 14.0.1, onder Kubuntu 12.04 met Linux kernel versie 3.2.0-27-generic. De tests werden uitgevoerd op een
Asus X53S K53SV, met een Intel Core i7 2630QM processor draaiende aan 2 GHz en 6 GB ram geheugen.

\subsection{Pagina laadtijd}

De pagina laadtijd hebben we gemeten door op een lokale webpagina een andere lokale pagina in te laden via een iframe.
De tijdstippen (\lstinline|new Date().getTime()|) worden opgenomen voor dat de pagina wordt ingeladen en als de pagina geladen is (door gebruik te maken van het onload event).
Er werd de gemiddelde laadtijd berekend van 1000 pagina herladingen, zowel van een pagina waar het prototype wordt ingeladen als van een lege pagina.
De gemiddelde laadtijd van de lege pagina was $85.65$ms ($\sigma = 59.53$ms).
De gemiddelde laadtijd van de pagina met het prototype was $238.23$ms ($\sigma = 88.13$ms).

\subsection{Code uitvoering}

De performantie overhead van de code uitvoering hebben we berekend door het nemen van de tijdstippen voor en na dat er een stuk code 10000 keer werd uitgevoerd.
Er zijn 3 stukken code zo uitgevoerd geweest: een \lstinline|cookie| access (set en get), een \lstinline|localStorage| access (set, get en delete), een request versturen (\lstinline|XMLHttpRequest| open en send).
De uitvoeringstijd werd berekend voor Spidermonkey, het prototype met een allow all policy en het prototype met een allow none policy.
De gemiddelde uitvoeringstijden zijn te zien in tabel \ref{resultaten_uitvoering}.

\begin{table}[h]
\centering
\begin{tabular}{l | l | l | l}
                  & \lstinline|cookie|            & \lstinline|localStorage|    & \lstinline|XMLHttpRequest|  \\
\hline
zonder prototype  & 0.33ms                        & 0.31ms                      & 8.34ms          \\
``Allow all''     & 0.88ms (+ 166\%)              & 0.55ms (+ 77\%)             & 9.35ms (+ 12\%) \\
``Allow none''    & 0.51ms (+  54\%)              & 0.50ms (+ 61\%)             & 0.67ms (- 92\%) \\
\end{tabular}
\caption{Code uitvoering overhead.}\label{resultaten_uitvoering}
\end{table}

Uit de resultaten is het duidelijk te zien dat de prototype een vrij zware performantie overhead heeft. 
Dit komt voornamelijk omdat de overhead van de pagina laadtijd zeer hoog is. Er zijn een aantal manieren om de performantie te verbeteren, zo zouden we het prototype kunnen compileren met de clojure compiler van google, dat de code optimaliseert en minimaliseert. Verder zouden we het prototype kunnen gzippen om de laadtijd verder te verbeteren.

\section{Beveiliging}

We hebben gezien hoe policies gemaakt en afgedwongen kunnen worden. Deze zouden hun waarde verliezen als ze kunnen worden omzeild.
In deze sectie wordt er beschreven hoe een aanvaller de policies toch nog kan omzeilen en hoe dit wordt tegengegaan in de implementatie.

Voor mogelijke aanvallen hebben we ons onder andere gebaseerd op de limitaties die door CaJa\cite{caja} en Self-Protecting JavaScript{selfprotectjs} beschreven worden. 
Eerst bespreken we enkele andere gerelateerde aanvallen die niet mogelijk zijn op onze architectuur, gevolgd door de potenti\"ele gevaren.
\begin{itemize}
\item Alle in Narcissus uitgevoerde code moet worden gecheckt door de policy. Elk pad naar eenzelfde functie moet op dezelfde manier behandeld worden door de policy.
Zoals reeds uitgelegd werd in sectie \ref{getValueExp} is dit het geval omdat deze check in de \lstinline|getValue()| en \lstinline|putValue()| methodes gebeurt. 
Dit is een belangrijk voordeel van onze aanpak. Zowel Caja als Self-Protecting JavaScript hebben hier meer problemen mee.

Deze verschillende paden naar dezelfde functies worden ook wel aliasen genoemd en kunnen worden onderscheiden in static en dynamic.
Bijvoorbeeld bij static aliasing moet er rekening gehouden worden dat \lstinline|document| en \lstinline|window.document| aliasen zijn van hetzelfde object.
Dynamic aliasing is iets complexer.
Zo wijst this oorspronkelijk naar het global object, maar kan bijvoorbeeld binnen de context van een object wijzen naar het object.
Hier kan misbruik van gemaakt worden door een aanvaller op verschillende manieren.
Deze zijn buiten de scope van onze thesis en voor mogelijke aanvallen refereren we naar gerelateerd werk\cite{selfprotectjsIssues}.

Dit is een van de redenen dat Caja het gebruik van \lstinline|this| en \lstinline|with| limiteert. 
Bij Self-Protecting JavaScript zijn opnieuw enkele aanvalsvectoren mogelijk die hier misbruik van maken.

\item Voor een deel van de functionaliteit maakt Narcissus gebruik van de builtin functies uit SpiderMonkey. 
Sommige van deze builtin functies hebben een callback functie als parameter, die zal opgeroepen worden door een mechanisme in SpiderMonkey.
Dit is geen probleem daar deze callback methode zelf eerst in Narcissus ge\"evalueerd wordt en er dus eigenlijk een verwijzing naar deze ge\"evalueerde functie wordt meegegeven.
\begin{lstlisting}[caption=XHR met callback functie,label=code:XHRcallback]
	// callback functie
	function onResponse() {
		if (xhReq.readyState != 4)  { 
			// do more
		}
 	}
	var xhReq = createXMLHttpRequest();
	xhReq.open("GET","request.php", true);
	xhReq.onreadystatechange = onResponse; // onResponse wordt meegegeven als callback functie
	xhReq.send(null);	// onResponse wordt opgeroepen vanuit SpiderMonkey
\end{lstlisting}

\item Het hernoemen van functies en properties is ook mogelijk. Wanneer een geblokkeerde functie wordt opgeroepen, wordt een dummy functie teruggegeven. Bij het toewijzen van de functie aan een andere variabele zal dan ook de dummy versie terug gegeven worden.
Ook bijvoorbeeld het hernoemen van het object dat de property bevat, waarop een policy toegepast wordt is mogelijk.
\begin{lstlisting}[caption=Object van property hernoemen,label=code:renameFunc]
	var d = document;		// d == document
	d.getElementById('x'); 	// => activePolicy.read[d] == activePolicy.read[document]
\end{lstlisting}
Dit leunt aan bij static aliasing, dus ook dit kan opgelost worden bij andere technieken.

\item Het gebruik van \lstinline|this|, \lstinline|let|, \lstinline|with| en dergelijke worden ge\"interpreteerd door Narcissus, \lstinline|this| wijst bijvoorbeeld naar het global object van Narcissus.
Sommige van de nieuwere features zijn nog niet ondersteund in Narcissus, maar deze die ondersteund zijn, maken niet rechtstreeks gebruik van de SpiderMonkey versie. 
\lstinline|let| wordt bijvoorbeeld nog behandeld als \lstinline|var|, voor \lstinline|with| is er wel een eigen implementatie gemaakt.
Dus ook deze features kunnen we ondersteunen in ons prototype. 

Bij andere technieken worden deze keywords dikwijls gevreesd vanwege hun dynamisch gedrag.
Zoals gezegd wordt \lstinline|with| momenteel bijvoorbeeld niet toegelaten door CaJa, en kan dit voor problemen zorgen bij Self-Protecting JavaScript.

\item Een eventlistener toevoegen aan een DOM element is enkel mogelijk door code of een functie mee te geven, niet door een string. Dit maakt dat ook dit veilig is in ons prototype omwille van dezelfde reden als callback functies.

\item Het gebruik van \lstinline|Function| blijft ook ondersteund. \lstinline|Function| is te vergelijken met \lstinline|eval|, en kan een string ook uitvoeren als code. Dit zou normaal ook in SpiderMonkey context uitvoeren, maar Narcissus heeft hiervoor ook een eigen versie die de code laat uitvoeren in Narcissus context. \lstinline|Function| wordt momenteel ook niet ondersteund door CaJa. Self-Protecting Javascript heeft dit probleem zoals gezegd niet. Wel zijn er andere problemen met \lstinline|Function| voor Self-Protecting JavaScript, maar deze hebben niets te maken met het evalueren van code.
\end{itemize}

Hier wordt nogmaals een groot voordeel van een interpreter t.o.v. bestaande technieken duidelijk. 
Door de werking van een interpreter is het eenvoudiger alle paden naar een bepaald object of functie op een veilige manier te onderscheppen.

Vanuit het standpunt van de aanvaller identificeren we twee overige manieren om de policy te omzeilen. 
\begin{itemize}
\item {\bf Het aanpassen van het Narcissus object in Narcissus context:} Een aanvaller zou er kunnen in slagen een referentie naar het Narcissus object te bemachtigen.
\item {\bf Code uitvoeren in SpiderMonkey context:} De aanvaller zou functies kunnen uitvoeren waarvoor Narcissus gebruik maakt van de SpiderMonkey versie. We hebben reeds gezien dat er geen probleem is bij callbacks, het probleem situeert zich wanneer er een string kan meegegeven worden. Strings worden in Narcissus ook ge\"interpreteerd als strings zonder meer. Een aanvaller kan dan gebruik maken van de functies die Narcissus gebruikt uit SpiderMonkey waarbij zonder interpretatie een string als code uitgevoerd wordt. Een aanvaller zou zo bijvoorbeeld de SpiderMonkey versie van eval kunnen proberen uitvoeren.
\end{itemize}

\subsection{Aanpassen van het Narcissus object}
Het Narcissus object wordt aangemaakt bij het inladen van de pagina. Het is beschikbaar in de context van SpiderMonkey. Een aanvaller zou het Narcissus object zo kunnen aanpassen dat zijn geblokkeerde functies toch uitgevoerd kunnen worden. 
Bijvoorbeeld listing \ref{code:narcissusAttack} waarbij de aangepaste evaluate uitgevoerd wordt, en zo de policy van binnen uit aangepast wordt. Dit is enkel mogelijk als de aanvaller een referentie naar het Narcissus object kan verkrijgen. 
Alle gekende referenties moeten daarom geblokkeerd worden in Narcissus.

Een voorbeeld is \lstinline|window.parent|, dit object wordt gebruikt door Narcissus en houdt eigenlijk de omgeving bij van Spidermonkey, waardoor via dit object Narcissus toch nog beschikbaar is.

Om deze objecten te verbergen, kan er gebruik gemaakt worden van een mechanisme van Narcissus zelf. Narcissus kan namelijk een blacklist bijhouden die bepaalde objecten kan verstoppen van het geheugen van de Narcissus context. 
Deze blacklist werd al gebruikt om Narcissus te verstoppen. Er moest dus enkel \lstinline|window.parent| aan de blacklist toegevoegd worden en zo het aanpassen van de policies onmogelijk maken vanuit de Narcissus context.

\medskip
\begin{lstlisting}[caption=Narcissus aanpassen,label=code:narcissusAttack]
	// Narcissus context
	Narcissus.interpreter.evaluate("alert(document.cookie);",{cookie-read : "yes"});
\end{lstlisting}


\subsection{Code uitvoeren in Spidermonkey context}

Alle code die in Narcissus wordt ingeladen, wordt ook ge\"interpreteerd door Narcissus en is dus onderhevig aan de policies.
Strings daarentegen kunnen wel code bevatten die niet als code ge\"interpreteerd worden.
Zoals vermeld maakt Narcissus gebruik van objecten in Spidermonkey om functies te kunnen uitvoeren.
Een aanvaller moet dus op zoek gaan naar manieren om een string mee te geven aan een functie die leidt tot interpretatie in SpiderMonkey context.
We splitsen deze op in drie delen, voornamelijk omdat de oplossingen voor de drie delen onafhankelijk zijn van elkaar.

\begin{enumerate}
\item {\bf Functies die strings evalueren als code:} het bekendste voorbeeld hiervan is \lstinline|eval|. Als een aanvaller zijn code kan laten uitvoeren in deze functie, voert deze rechtstreeks in SpiderMonkey uit en dus zonder policy.
\item {\bf Het script element:} een aanvaller kan een nieuw script element toevoegen aan de dom, die daarna ook rechtstreeks in SpiderMonkey zal evalueren.
\item {\bf HTML injectie:} wanneer het toegelaten is voor een aanvaller om te schrijven naar de dom, zijn er verschillende mogelijkheden om nieuwe code te injecteren. Bijvoorbeeld door een nieuwe script tag toe te voegen met \lstinline|innerHTML|.
\end{enumerate}

Deze drie delen komen ook terug in de meeste andere technieken. Al zal dikwijls de werkwijze van de oplossing verschillen vanwege onze architectuur. Geen enkel van de overige aanvallen is toepasbaar op Self-Protecting JavaScript. In de volgende stukken stellen we mogelijke oplossingen voor. Daarin zullen we dus enkel nog de vergelijking met Caja maken.

\subsubsection{Functies die strings evalueren}
Functies die een string als parameter hebben, waarbij de string uitgevoerd wordt zoals de \lstinline|eval()|-methode, kunnen rechtstreeks uitvoeren in SpiderMonkey.
Narcissus heeft al reeds een aanpassing voor de \lstinline|eval()|-methode. De aangepaste \lstinline|eval()|-methode is eigenlijk gewoon een variant van de \lstinline|Narcissus.interpreter.evaluate()|-methode. 

Zoals ook aangegeven door de makers van Narcissus, zijn er buiten eval nog functies die een string als code kunnen interpreteren. Met name \lstinline|setTimeout| en \lstinline|setInterval|. Om deze code toch veilig uit te voeren moet er extra code toegevoegd worden. In dit voorbeeld wordt \lstinline|setTimeout| geherdefinieerd in Narcissus context, waarbij de \lstinline|setTimeout| uit SpiderMonkey opgeroepen wordt.
\begin{lstlisting}[caption=Aangepaste setTimeout,label=code:setTimeout]
	// Prevent setTimeout from breaking out to SpiderMonkey
	setTimeout: function(code, delay) {
 		var timeoutCode = (typeof code === "string") ?
			function() { Narcissus.interpreter.evaluate(code); } :
				code;
		return setTimeout(timeoutCode, delay);
	}
\end{lstlisting}
Caja lost het probleem met \lstinline|eval| niet op en ondersteunt het simpelweg niet. \lstinline|setTimeout| en \lstinline|setInterval| zouden wel ondersteund worden. Dit staat momenteel nog aangegeven als mogelijke aanvalsvector\cite{cajaattacks}, wat ons doet vermoeden dat ze hiervoor nog geen concrete oplossing hebben.

\subsubsection{Aanmaken van script element}
De DOM API laat toe nieuwe scripts toe te voegen. 
Zo een script element wordt pas uitgevoerd als het aan het document toegevoegd is. 
De code die het element moet uitvoeren kan op verschillende manieren bepaald worden.
Zo kan er gebruik gemaakt worden van de "text" property zoals in het voorbeeld(listing \ref{code:newscriptelement}), maar hetzelfde effect wordt verkregen door het toevoegen van een \lstinline|textNode| als \lstinline|childNode| van het script element.

\medskip
\begin{lstlisting}[caption=Nieuw script toevoegen aan de DOM via JavaScript,label=code:newscriptelement]
        var g = document.createElement('script');
        var s = document.getElementsByTagName('script')[0];
        g.text = "alert('via createElement script: ' + document.cookie);"
        s.parentNode.insertBefore(g, s);
\end{lstlisting}
Buiten het invoeren van code via strings kan er ook gebruik gemaakt worden van de "\lstinline|src|" property, 
die bij het toevoegen van het script element, het bestand op de gegeven locatie gaat inladen en de inhoud ervan gaat uitvoeren als code.
Om deze scripts toch in Narcissus te laten uitvoeren herdefini\"eren we het script element lichtjes bij de creatie ervan.
Spidermonkey definieert een functie $"$\lstinline|onbeforescriptexecute|$"$ die uitgevoerd wordt net voor het uitvoeren van de eigenlijke code.
Dit afdwingen kan handig gedaan worden dankzij de policy die nu reeds in Narcissus zit, door een extra policy hardcoded af te dwingen (zie listing \ref{code:scriptelementredef} ). 

\medskip
\begin{lstlisting}[,caption=createElement variant,label=code:scriptelementredef]
	ruleSet.read[document]["createElement"] = function(tagName){
				var element = document.createElement(tagName);
				element.onbeforescriptexecute = function(evt){
						try{
							if(this.src){
								evaluateUrl(this.src,JSON_active_policy);
							}
							if(this.text){
								evaluate(this.text,JSON_active_policy);
							}
						}catch(e){}
						return false;
				}
				return element;
		}
\end{lstlisting}

\lstinline|onbeforescriptexecute| is geen standaard property, maar zit al sinds gecko 2.0 in Firefox.
Als deze functie \lstinline|false| als returnwaarde heeft dan wordt het script niet verder uitgevoerd. 
Hiervan maken we gebruik door de eventuele \lstinline|src| in de \lstinline|evaluateUrl()|-methode en de eventuele text in de \lstinline|evaluate()|-methode uit te voeren om vervolgens sowieso \lstinline|false| terug te geven.
Hierbij is het \lstinline|try|/\lstinline|catch| block ook van belang, stel dat er een error wordt gegooid op het einde van het script dan zou de $"$\lstinline|return false|$"$ niet uitgevoerd worden en kan het script alsnog in SpiderMonkey uitgevoerd worden.

Als laatste moeten we er dan nog enkel voor zorgen dat het \lstinline|onbeforescriptexecute|-attribuut niet meer gewijzigd kan worden. 
Dit wordt afgedwongen in de \lstinline|putValue()|-methode, door het type te checken en het attribuut dat aangepast moet worden (zie listing \ref{code:onbeforescriptblock}).
Hier werkt onze policy niet omdat er oneindig veel scripts kunnen aangemaakt worden, met elk een unieke referentie. 

\medskip
\begin{lstlisting}[caption=onbeforescriptexecute onaanpasbaar maken,label=code:onbeforescriptblock]
	function putValue(v, w, vn) {
		if (v instanceof Reference) {
			if(v.base instanceof Element && v.propertyName === "onbeforescriptexecute")
				return null;
		...
\end{lstlisting}

Hierdoor kan men de \lstinline|onbeforescriptexecute| methode niet meer gebruiken, aangezien dit geen standaard attribuut is en niet ondersteund is in de meeste andere browsers hoeft dit niet als een minpunt aanzien worden.

Net als de vorige aanval, wordt deze methode bij Caja ook vermeld onder mogelijke aanvalsvectoren\cite{cajaattacks}.

\pagebreak

\subsubsection{HTML injectie}
Een wederkerend probleem is het feit dat JavaScript functies aanbied die nieuwe HTML tags in de DOM kan schrijven (\lstinline|document.write|, \lstinline|Element.innerHTML|, ...). 
Deze zijn niet zo eenvoudig om op te lossen, Narcissus kan enkel JavaScript evalueren en het parsen van HTML is een zeer complexe operatie.
Eerst wordt er beschreven hoe dit opgelost wordt voor \lstinline|innerHTML|, gevolgd door een vergelijking met andere functies.

De property \lstinline|innerHTML| kan gezet worden voor elke Element node in de DOM, en verwacht als waarde een string.
Als in listing \ref{code:innerHTMLex1} kan deze string dus bestaan uit html-tags. Hierdoor kan op verschillende manieren JavaScript uitgevoerd worden. 
Deze kunnen onder 3 methodes geclassificeerd worden, eerst worden ze kort toegelicht en verder zal er voor elk type een oplossing geboden moeten worden.

\medskip
\begin{lstlisting}[caption=Voorbeeld innerHTML met nieuwe paragraaf,label=code:innerHTMLex1]
	var div = document.createElement('div');
	div.innerHTML = "<p>nieuwe paragraaf</p>";
	document.body.appendChild(div);
\end{lstlisting}

\begin{itemize}
\item Het eerste type is door het invoeren van script tags,
waar zoals bij het aanmaken van een script element, ook de text of de inhoud van een bestand in Narcissus moet ge\"evalueerd worden. 
\medskip
\begin{lstlisting}[caption=Voorbeeld innerHTML met script tag,label=code:innerHTMLex2]
	div.innerHTML = "<script>alert(document.cookie);</script>";
\end{lstlisting}

\item Als tweede type nemen we de events die elk element kan uitvoeren. 
Bijvoorbeeld een image element met de property \lstinline|onload|, waarbij de value als string uitgevoerd wordt wanneer de afbeelding geladen is. 
Zoals gezegd kan er geen misbruik van gemaakt worden via deze events in JavaScript, de events verwachten daar een stuk code en geen string, zoals een callback functie.

\medskip
\begin{lstlisting}[caption=Voorbeeld innerHTML met element met onload event,label=code:innerHTMLex3]
	div.innerHTML = "<img src='my_image.gif' onload='alert(document.cookie);' />";
\end{lstlisting}

\item Als derde en laatste zijn er nog enkele uitzonderingen, deze categorie kan gezien worden als de XSS (Cross Site Scripting) categorie.
Bepaalde properties laten het ook toe om JavaScript uit te voeren. Bijvoorbeeld voor \lstinline|onclick|, zal bij het klikken op het element, het script uitgevoerd worden.
\medskip
\begin{lstlisting}[caption=Voorbeeld innerHTML met JavaScript in href,label=code:innerHTMLex4]
	div.innerHTML = "<a href='javascript:alert(document.cookie);' >Klik hier</a>";
\end{lstlisting}
\end{itemize}
\subsubsection{innerHTML}

Het eenvoudige stuk is er voor zorgen dat de waarde niet aan de originele \lstinline|innerHTML| toegekend wordt. 
Dit kan opnieuw gedaan worden zoals $"$\lstinline|onbeforescriptexecute|$"$, een extra \lstinline|if| die nagaat of het attribuut \lstinline|innerHTML| is.
En in plaats van aan \lstinline|innerHTML| toe te kennen een eigen functie uit te voeren.

Voor het moeilijke stuk, het interpreteren van de HTML, zijn er meerdere problemen op te lossen. 
Er is geen HTML parser beschikbaar en een XML parser zou enkel werken voor XHTML stricte syntax. Ook is het bijvoorbeeld niet mogelijk om vanuit JavaScript, JavaScript tijdelijk af te zetten. 

Er is dus een alternatief nodig voor het parsen van HTML.
Hiervoor kunnen we gebruik maken van \lstinline|innerHTML|, door \lstinline|innerHTML| te zetten van een element kan een string ook geparset worden naar nodes. Een belangrijk nadeel is wel dat ook script tags dan worden uitgevoerd alsook de events toegevoegd aan de geparsete elementen.

Een eerste belangrijke opmerking is dat scripts pas uitgevoerd worden, vanaf het moment dat ze aan het document hangen. We lossen dit dus op door \lstinline|innerHTML| uit te voeren op een element dat niet aan het document vasthangt.
Helaas geldt dit niet voor events, e.g. \lstinline|onload| van een \lstinline|img|-tag wordt toch uitgevoerd wanneer een afbeelding geladen is.
Om dit te vermijden wordt er eerst een reguliere expressie uitgevoerd op de hele string, die alle events (attributen die beginnen met on), hernoemt waardoor deze niet meteen uitgevoerd worden maar toch nog opgevraagd kunnen worden nadat ze geparset zijn.
\medskip
\begin{lstlisting}[caption=Gebruik nieuwe div als HTML parser, label=code:innerHTMLparse]
	var div = document.createElement("div");
	div.innerHTML = htmlString;
\end{lstlisting}

De reguliere expressie in listing \ref{code:regexEvents} is gekozen omdat events altijd beginnen met on (e.g. \lstinline|onload|, \lstinline|onblur|, ..), 
gevolgd door een \lstinline|=| teken waartussen zich spaties kunnen bevinden. 
Deze is bewust zeer los gekozen, om te vermijden dat deze expressie omzeild kan worden, 
het is bijvoorbeeld niet nodig dat er quotes gebruikt worden na het \lstinline|=| teken om ge\"interpreteerd te worden. 
Het nadeel is dat er tekst ongewenst aangepast kan worden (E.g. \lstinline|<p>one = een</p>| "). Dit wordt later opgelost.
\medskip
\begin{lstlisting}[caption=Reguliere expressie die events vervangt,label=code:regexEvents]
	// met elem als ingegeven html-string
	elem = elem.replace(/ (on)(\w+) *=/ig, ' $1$2narc=');
\end{lstlisting}

Na dat we de \lstinline|innerHTML| veilig hebben kunnen oproepen, kunnen we gebruik maken van de \lstinline|childNodes| van het losse element.
Stel dat we \lstinline|innerHTML| willen uitvoeren, dan kunnen we deze \lstinline|childNodes| toevoegen aan het element waar oorspronkelijk de \lstinline|innerHTML| van gezet werd. 
Voor dat dit gedaan wordt moeten alle nodes eerst nagekeken worden. Zodat de 3 eerder beschreven types toch correct kunnen worden uitgevoerd.

Voor het eerste type wordt er gekeken of de node een script element is, indien dit het geval is slagen we het script (\lstinline|src| en/of text) op in een \lstinline|Object|. Het \lstinline|Object| heeft een functie \lstinline|execute|, dat net als bij \lstinline|onbeforescriptexecute|, de code in Narcissus uitvoert. 
Dit \lstinline|Object| wordt aan een lijst toegevoegd. De index die het krijgt in deze lijst zal gebruikt worden om vanuit SpiderMonkey context dit script uit te voeren. Het oorspronkelijke script wordt vervangen door een nieuw script dat de nieuwe methode \lstinline|evaluateScript(scriptId)| gebruikt. \lstinline|evaluateScript| neemt het script op de gegeven index en voert het uit. Op deze manier wordt ook de correcte volgorde van uitvoeren behouden. 

\medskip
\begin{lstlisting}[caption=Script element in Narcissus laten uitvoeren, label=code:type1scripts]
var rWrongProps = / (on)(\w+)narc=/ig;
 if ( nodeName( script, "script" ) && (!script.type || /\/(java|ecma)script/i.test( script.type )) ) {
	var scriptId = narcScripts.length;
	if(script.text && rWrongProps.test(script.text))
		script.text = script.text.replace(rWrongProps," $1$2=");
	narcScripts[scriptId] = new NarcScript(script);
	var newScript = elem.ownerDocument.createElement("script");
	newScript.appendChild(elem.ownerDocument.createTextNode("Narcissus.interpreter.evaluateScript("+scriptId+");"));
	elem.parentNode.replaceChild(newScript,elem);
	elem = newScript;
}
...
// Object dat als parameter een script element nodig heeft en dit gebruikt om uit te voeren in Narcissus
var NarcScript = function(script){
	this.src = script.src;
	this.text = script.text;
	this.execute = function(){
		if(this.src)
			evaluateUrl(this.src, JSON_active_policy);		
		else if(this.text)
			evaluate(this.text, JSON_active_policy);
	}
}
\end{lstlisting}

\begin{lstlisting}[caption=De evaluateScript methode, label=code:evaluateScript]
	var narcScripts = [];
	function evaluateScript(id){
		if(typeof id === "number" && narcScripts[id]){
			narcScripts[id].execute();
		}
	}
\end{lstlisting}

Merk ook op dat, indien het een inline script is, er nog een reguliere expressie op uitgevoerd wordt. Dit wordt gedaan omdat het mogelijk is dat de reguliere expressie die events aanpast, ook de scripts aanpast.

\begin{lstlisting}[caption=Script dat foutief zou worden aangepast]
var onload = "test"; // wordt var onloadnarc= "test";
alert(onload); // blijft alert(onload); 
\end{lstlisting}

\pagebreak

\subsubsection{Events}

Het 2de type dat nagekeken moet worden zijn de events. 
Deze zijn zoals eerder beschreven hernoemd via een reguliere expressie. 
Alle attributen van elk element worden afgegaan en met een nieuwe reguliere expressie wordt nagegaan of de attribuut een event is.
Indien dit zo is, wordt de eigenlijke actie eruit gefilterd (e.g. \lstinline|onloadnarc = load|).
Voor deze kan dan een eventlistener toegevoegd worden aan het element. Hoe dit juist gebeurt, wordt later uitgelegd.
De attributen waarvoor een eventlistener is toegevoegd worden verwijderd van het element. Deze zijn nu vervangen. 
Als laatste wordt er voor elke \lstinline|childNode| gecheckt of er een \lstinline|textNode| tussenzit.
Op elke \lstinline|textNode| wordt dan nog een reguliere expressie uitgevoerd, die er voor moet zorgen dat de text die eventueel is aangepast door de eerste expressie, terug vervangen wordt door de oorspronkelijke text.

\medskip
\begin{lstlisting}[caption=Events in Narcissus laten uitvoeren, label=code:type2scripts]
	// elem is het element dat gecheckt wordt
	var to_remove = [];
	var rEventPropNarc = /on(\w+)narc/ig; // regex die attributen checkt op events
	for(j in elem.attributes){
		let attr = elem.attributes[j].name;
			if(rEventPropNarc.test(attr)){ // check of het een event is
				let action = attr.replace(rEventPropNarc,'$1'); // filter de eigenlijke actie
				(function() {
					let code = elem.getAttribute(attr);
					attachNarcissusEvent(action,code,elem);
				})();
				to_remove[to_remove.length]= attr;
			}
		}
		for(rAttr in to_remove)
			elem.removeAttribute(to_remove[rAttr]); // verwijder attributen
		.. check op textNodes..
\end{lstlisting}

\subsubsection{XSS aanvallen}

Voor het 3de type, de XSS manier, hebben we de XSS cheat sheet\cite{XSScheatsheet} afgegaan, 
en gekeken welke aanvallen kunnen uitgevoerd worden op deze implementatie. Dus enkel aanvallen die in Firefox werken, 
kunnen van toepassing zijn op het prototype. De 2 overblijvende aanvallen waren het misbruik van \lstinline|src| en \lstinline|href| attribuut (zoals in \ref{code:innerHTMLex4}). 
Wanneer men deze in SpiderMonkey context test merkt men geen verschil tussen \lstinline|href| met \lstinline|onclick| en \lstinline|src| met \lstinline|onload|. 
Deze observatie laat toe dezelfde methode als type 2 te gebruiken mbhv een extra \lstinline|if|.

\pagebreak

\medskip
\begin{lstlisting}[caption=Speciale attributen met JavaScript in Narcissus laten uitvoeren, label=code:type3scripts]
	var rJSexec = /javascript:/ig;
	var risky = {'src' : 'load', 'href' : 'click'};
	...
	else if(risky[attr] && rJSexec.test(elem.getAttribute(attr))){ // catch other xss attacks
		(function() {
			let code = elem.getAttribute(attr).replace(rJSexec,"");
			attachNarcissusEvent(risky[attr],code,elem);
		})();
		elem.setAttribute(attr, "javascript:");
		to_remove[to_remove.length]= attr;
	}
\end{lstlisting}

Als de waarde van het attribuut $"$\lstinline|javascript:|$"$ bevat, wordt het verwijderd en wordt het verder afgehandeld als bij type 2, bepaald door de lijst $"$\lstinline|risky|$"$. 
Belangrijk is dat dit in tegenstelling tot bij events er in de JavaScript code ook misbruik kan gemaakt worden van deze methode (vb zie listing \ref{code:vulnerXss}).
De check die reeds bestaat in \lstinline|putValue| moet dus worden aangevuld met deze check.
Het principe is hetzelfde als in \ref{code:type3scripts} en wordt daardoor niet opnieuw beschreven.
\medskip
\begin{lstlisting}[caption=javascript uitvoeren via href, label=code:vulnerXss]
	var a = document.createElement('a');
	a.href="javascript:alert(document.cookie);";
	document.body.appendChild(a);
\end{lstlisting}

Als laatste deel moeten de functies nog gekoppeld worden aan de juiste events van het juiste element.
Code in een element heeft een eigen scope, zo is this niet het \lstinline|window| object, maar het element zelf.
Een paragraaf kan bijvoorbeeld onzichtbaar gemaakt worden door er op te klikken.
\medskip
\begin{lstlisting}[caption=verbergen van een paragraaf via onclick, label=code:hideParag]
	<p onclick="this.style.visibility='hidden';">verberg mij</p>
\end{lstlisting}

Als we gewoon de \lstinline|evaluate()| methode gebruiken dan zou dit dus niet het gewenste effect geven.
Er is nood aan een oplossing die zowel $"$\lstinline|style|$"$ als $"$\lstinline|this.style|$"$ herkent als eigenschappen van het element waarop de eventlistener uitgevoerd wordt. Hiervoor gebruiken we de \lstinline|getValue()| en \lstinline|putvalue()| methodes opnieuw. 
De eventlistener die we toevoegen, zet een tijdelijke variabele in Narcissus voor het uitvoeren van de eigenlijke code.
Dit is mogelijk omdat de eventlistener zelf in Spidermonkey context uitvoert en daardoor aan het Narcissus object kan. 
Als tijdelijke variabele gebruiken we dan het element, in \lstinline|getValue()| moet dan enkel gecheckt worden of het element al dan niet undefined is, en indien het bestaat, kan dat element als \lstinline|this| gebruikt worden.
 
\pagebreak
 
\medskip
\begin{lstlisting}[caption=eventlistener toevoegen aan element, label=code:attachevent]
	var eventHook = {element : undefined}
	var attachNarcissusEvent = function(action, code, element){
		let f = '(function() { ' + code + '})();';
		let fun = function(evnt){
			Narcissus.interpreter.eventHook.element = element; // hook to execute in the right context
			Narcissus.interpreter.global.event = evnt;
			Narcissus.interpreter.evaluate(f);
			Narcissus.interpreter.global.event = undefined;
			Narcissus.interpreter.eventHook.element = undefined;
		};
		element.addEventListener(action, fun, false);
	}
\end{lstlisting}

\medskip
\begin{lstlisting}[caption=Extra code in getValue om in de juiste scope uit te voeren, label=code:eventHook]
	if(eventHook.element !== undefined && v.base === global && eventHook.element.hasOwnProperty(v.propertyName))
		v.base = eventHook.element; // hook for events
	...
	return v.base[v.propertyName];
\end{lstlisting}

Als laatste mogelijkheid is er nog de \lstinline|iframe| die zowel via JavaScript als via HTML kan ingevoegd worden. 
Door een link mee geven in het \lstinline|src| attribuut, kan een externe webpagina geladen worden. 
Deze kan zijn eigen origine hebben, de html kan dan ook niet zomaar gedownload worden via XHR aangezien het van een ander domein afkomstig is. Door deze problemen is dit niet vanzelfsprekend om iframes te ondersteunen, we opteren dan ook om iframes niet toe te laten.

Het toepassen van deze methode met \lstinline|innerHTML|, op een functie als \lstinline|document.write| brengt nog enkele extra problemen met zich mee. Bij \lstinline|document.write| kan de html in stukken geschreven worden, en nog altijd als een element ge\"interpreteerd worden bvb. 
\lstinline|document.write('<p>');document.write('test');document.write('</p>');| zal als een paragraaf verschijnen in de DOM. 
Met de huidige methode zou men 2 paragrafen met een textnode ertussen krijgen. 
Om dit op te lossen checken we of de string die geschreven moet worden geldige xml is, en indien dit zo is, 
worden de elementen die aangemaakt zijn door de functie aan de body gehangen. 
Dit is een eerder na\"ieve methode en zal nooit foute xhtml schrijven naar de DOM, maar volstaat voor dit prototype. 
De prioriteit binnen deze thesis is gegaan naar het testen en beveiligen van Narcissus.

Als we deze methode vergelijken met Caja zien we dat deze sterk gerelateerd is. Caja verwijdert alle verboden tags en attributen volgens een aantal filters\cite{cajalimit}. Wat ongeveer wel op hetzelfde neer komt, ondanks het implementatieverschil.

\pagebreak

\section{Beperkingen}

Deze sectie geeft een overzicht van de beperkingen die ons systeem nog heeft, een deel
van deze beperkingen zijn reeds aan bod gekomen in de vorige stukken.

\subsubsection{Narcissus.interpreter.evaluateURL()}

Deze methode wordt gebruikt om externe JavaScript bestanden in te laden. Zoals in hoofdstuk \ref{Narcissus} te zien was, maakt
deze methode gebruik van het XMLHttpRequest object. Omdat het XHR object beperkt wordt door de same-origin policy is het dus niet mogelijk om bestanden die van andere origines afkomstig zijn uit te voeren.
Er is geen manier om deze beperking te omzeilen via JavaScript zonder gebruik te maken van een browser addon.
Een andere mogelijke oplossing voor dit probleem zou kunnen zijn dat de bestanden op de server kunnen gedownload worden door een server-side script dat opgeroepen wordt door Narcissus. 

\begin{lstlisting}[caption=XHR met server-side script.]
 function evaluateUrl(u, p, f, l){
    //maakt gebruikt van het server-side script op de lokale server
     eval_req.open('GET', 'http://my.origin.com?get_file.php?url=' + u , false); 
     eval_req.send(null);
     if (eval_req.status !== 200) {
        throw new Error("Error loading " + u);
     }
     return evaluate(eval_req.responseText,p,f,l);
  }
\end{lstlisting}

Deze beperking is dan ook het gevolg van doelstelling D4. De browser biedt geen alternatief aan en de browser mag niet worden aangepast.
Dit wil ook zeggen dat andere technieken zoals Caja\cite{caja} en FBJS\cite{fbjs} hetzelfde probleem hebben.
Voor dit probleem wordt het gebruik van inline script als mogelijke work around aangegeven.

Een uitzondering die doelstelling D4 wel haalt, is de aanpak van Self-Protecting JavaScript\cite{selfprotectjs}. Door dat deze aanpak de referenties naar de functies in de global scope aanpast, is dit wel mogelijk.
De ingeladen scripts maken gebruik van de aangepaste functies, die rond de originele functies zijn geweven.
Helaas kunnen we deze aanpak niet voor onze architectuur gebruiken zonder de gekende beveiligingsproblemen van Self-Protecting JavaScript.

\subsubsection{iFrame}

Zoals eerder vermeld wordt de \lstinline|iframe| niet ondersteund. Er zijn twee mogelijke manieren om een \lstinline|iframe| te gebruiken. Een \lstinline|iframe| kan
ge\"inlined worden als html of er kan een pagina in een iframe geladen worden door gebruik te maken van het \lstinline|frame.src| attribuut.

Als er gebruik wordt gemaakt van het \lstinline|frame.src| attribuut zijn er opnieuw problemen door de same-origin policy.
Een frame dat een source heeft in een andere origin kan niet aangepast worden in JavaScript. Deze frame kan dan terug code uitvoeren in SpideMonkey zonder dat de policy er nog invloed op heeft.

Opnieuw komen ook hier de andere technieken in de problemen. Caja ondersteunt iframes helemaal niet.
Self-Protecting JavaScript laat ook toe iframes te blokkeren, omdat er verschillende aanvalsvectoren mogelijk zijn die gebruik maken van iframes.

Als html ge\"inlined wordt zit de \lstinline|iframe| wel in dezelfde origin, hierdoor lijkt het wel mogelijk om deze methode te ondersteunen.
Het prototype ondersteunt deze methode echter nog niet omdat er hier nog andere problemen mee zijn.
Het prototype kan inline iframes nog niet correct parsen, de reden hiervoor is nog niet voldoende onderzocht.


\subsubsection{document.write()}

Deze functie kan enkel nog gebruikt worden om xhtml strict te schrijven naar het document (plaintext wordt ook bezien als xhtml stict). De functieoproepen worden wel gebufferd totdat er een xhtml strict stuk tekst in de buffer zit. Zo kan een stuk tekst met meerdere write operaties geschreven worden.

\medskip
\begin{lstlisting}[caption=Gebufferde document.write()., label=code:buffer]
 //schrijft <p>Hello, world!</p> naar het document
 document.write('<p>');
 document.write('Hello, world!');
 document.write('</p>');
\end{lstlisting}

De reden dat het prototype enkel xhtml strict aanvaardt voor de \lstinline|document.write()| methode is dat onze implementatie onvolledige tags atlijd zal afsluiten. Als er niet zou gebufferd worden tot er xhtml stricte tekst geschreven kan worden zou het voorbeeld in listing \ref{code:buffer} resulteren in twee lege paragrafen met een stuk tekst ertussen.

Een extentie op deze oplossing is om alle niet geschreven \lstinline|document.write()| oproepen ook te bufferen tot het \lstinline|document.onload| event afgevuurd wordt.  Dit event wordt enkel afgevuurd als het document volledig klaar is en zullen dus alle mogelijke \lstinline|document.write()| oproepen al opgeroepen zijn. Deze oplossing is niet perfect omdat de locatie waar er \lstinline|document.write()| opgeroepen wordt effect heeft op het resultaat ervan.

Onze aanpak heeft gelijkaardige beperkingen als Caja\cite{cajalimit}, omdat het een gelijkaardige aanpak gebruikt. Self-Protecting JavaScript heeft hier opnieuw hetzelfde voordeel en kan dit dus wel gewoon toelaten.

\subsubsection{Flash}

Het is ook mogelijk om vanuit Flash JavaScript uit te voeren. De JavaScript code die door flash uitgevoerd wordt draait in de context van SpiderMonkey, zo kunnen de policies dus omzeild worden. 
Er is geen duidelijke oplossing voor dit probleem buiten flash volledig te blokkeren.